using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Entity.Infrastructure;
using ShopPowerTemplate.Services.Properties;
using ShopPowerTemplate.Entities;
using System.Linq.Expressions;

namespace ShopPowerTemplate.Services
{
    public class ProductService : ProductServiceBase, IProductService
    {
		public ProductService(IEntitiesDB entitiesDB) : base(entitiesDB) { }

        public bool StockAvailable(Product product, IEnumerable<Option> selectectOptions)
        {
            var options = selectectOptions.Select(so => so.Id);

            if (selectectOptions == null || selectectOptions.Count() == 0)
                return EntitiesDB.ProductSet
                    .Include("ProductDetails")
                    .Any(p => p.ProductDetails
                        .Any(pd => pd.Stock > 0));
            else
            {
                return EntitiesDB.ProductDetailSet
                    .Include("Product")
                    .Include("Option")
                    .Any(pd => pd.Product.Id == product.Id &&
                        pd.Stock > 0 &&
                        pd.Option.Select(o => o.Id).All(oid => options.Any(so => so == oid)));
            }
        }

        //Custom code here
        public List<Product> SearchCustomByPrice(Func<Product, bool> searchCriteria)
        {
            var t = EntitiesDB.ProductSet.Include("Subcategory.Category").Where(searchCriteria).OrderBy(p => p.Price).ToList();
            return t;
        }

        public List<Product> SearchCustomByName(Func<Product, bool> searchCriteria)
        {
            //var t = EntitiesDB.ProductSet.Include("Subcategory.Category").Where(searchCriteria).OrderByDescending(p => p.Name).ToList();
            var t = EntitiesDB.ProductSet.Include("Subcategory.Category").Where(searchCriteria).OrderBy(p => p.Name).ToList(); //Tito 07-12-12 El orden era inverso
            return t;
        }

        public List<Product> SearchCustomByRating(Func<Product, bool> searchCriteria)
        {
            var t = EntitiesDB.ProductSet.Include("Subcategory.Category").Include("Reviews").Where(searchCriteria).OrderByDescending(pp => pp.AverageReview).ToList();
            return t;
        }

        public List<Product> SearchCustomByProminentAndName(Func<Product, bool> searchCriteria)
        {
            var t = EntitiesDB.ProductSet.Include("Subcategory.Category").Where(searchCriteria).OrderByDescending(p => p.Prominent).ThenByDescending(pp => pp.Name).ToList();
            return t;
        }

        public Image GetFirstProductImage(int productId)
        {
            return GetAllProductImage(productId).FirstOrDefault();
        }

        public IEnumerable<Image> GetAllProductImage(int productId)
        {
            IEnumerable<Image> result = Enumerable.Empty<Image>();

            Product product =
                EntitiesDB.ProductSet
                    .Include("Images")
                    .FirstOrDefault(x => x.Id == productId);

            if (product != null && product.Images != null && product.Images.Count > 0)
                result = product.Images.OrderBy(i => i.SortOrder);

            return result;
        }

        public IEnumerable<Product> GetProminentProducts()
        {
            return EntitiesDB.ProductSet.Where(p => p.Prominent).OrderBy(p => p.Name);
        }

        //Override methods
        public override Product Find(int id)
        {
            Product product =
                EntitiesDB.ProductSet
                    .Include("Subcategory")
                    .Include("Images")
                    .Include("Reviews")
                    .Include("ProductDetails.Option")
                    .FirstOrDefault(x => x.Id == id);

            if (product != null)
            {
                var subcategoryAux = product.Subcategory; //EF4.1 bug hack
            }
            return product;
        }


        public IEnumerable<OptionType> GetOptionTypes(int productId)
        {
            return EntitiesDB.OptionTypeSet
                    .Include("Options.ProductDetails")
                    .Where(ot => ot.Options.Any(o => o.ProductDetails.Any(pd => pd.Product.Id == productId))).Distinct();
        }
	}
}	

